package dinnerSimulation;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;

import dlvwrapper.DlvWrapper;


public class AgentCiccioOne extends AgentCiccio {


	private List<Coord> meal_ready_actions = new ArrayList<Coord>();
	private List<Coord> suit_up_actions = new ArrayList<Coord>();
	private List<Coord> take_meal_actions = new ArrayList<Coord>();
	private List<Coord> table_ready_actions = new ArrayList<Coord>();
	private List<Coord> flowers_taken_actions = new ArrayList<Coord>();
	private List<Coord> entrance_actions = new ArrayList<Coord>();

	private DlvWrapper dlvwrapper;
	private int nextPos;
	private int nextRoom;
	public boolean init;


	public AgentCiccioOne(int x, int y, int opBound) {
		super(x, y, opBound);

		init = false;

		this.dlvwrapper = new DlvWrapper();
	}



	


	/**
	 * @return true if the agent has reached the goal
	 */
	public boolean goalReached() {
		return goalReached;
	}

	/**
	 * Make the agent perceives from environment
	 * 
	 * @param perception
	 *            current perception from the environment
	 */
	public void perceives(Perception perception) {
		this.perception = perception;
	}

	@Override
	public void update() {
		if (init)
			executeAction();
		else {
			print_back();
			print_initial(x, y);
			
			executePlan();
			executeAction();
			init = true;
		}

	}

	/**
	 * Print the list of agent actions
	 */
	public void showActions() {
		for (int i = 0; i < actionList.size(); i++)
			System.out.println(actionList.get(i).type);
	}

	/**
	 * Add the current action to the agent action list
	 * 
	 * @return current action of the agent
	 */
	public Action.Type action() {
		if (actionList.size() == 0) {
			perception.floor.set(x, y, dinnerSimulation.Square.Type.CLEAN);
		}
		actionList.add(new Action(currAction, x, y));
		// System.out.println("currAction ->  x= " + x + " y= " + y);
		return currAction;
	}

	/**
	 * 
	 * @param x
	 *            room di ciccio
	 * @param y
	 *            pos di ciccio
	 */

	public void print_back() {
		String obj = "\n";
		String doors = "\n";
		String room = "\n";
		String adj = "\n";
		String position = "\n";

		int pos;

		obj += "object(ciccio). object(meal). object(flowers). object(table). "
				+ "object(smoking). object(entrance).";
		System.out.println("l"+perception.floor.length + "w" +perception.floor.width);
		for (int k = 0; k < perception.floor.width; k++)
			position += "\nposition(" + (k + 1) + ").";

		for (int i = 0; i < perception.floor.length; i++) {
			int rpos = i + 1;
			room = room + "room(" + (i + 1) + ","
					+ perception.floor.room[i].toString().toLowerCase()
					+ " ).\n";
			System.out.println(perception.floor.length + "lenght floor");

			for (int j = 0; j <= perception.floor.width; j++) {
				pos = j + 1;

				if (perception.floor.get(i-1, j) == Square.Type.DOOR && perception.floor.room[i] == Floor.roomType.ENTRANCE){
					perception.floor.set(i, j, Square.Type.ENTRANCE);
					System.out.println("Square type settato Entrance");
				}
				
				if (perception.floor.get(i, j) == Square.Type.DOOR
						&& perception.floor.room[i] != Floor.roomType.ENTRANCE
						&& !(j == (y + 1) && perception.floor.room[x] == perception.floor.room[i])) {
					doors = doors
							+ "\ndoor_at("
							+ perception.floor.room[i].toString().toLowerCase()
							+ ","
							+ perception.floor.room[i + 1].toString()
									.toLowerCase()
							+ ","
							+ pos
							+ ").\n"
							+ "door_at("
							+ perception.floor.room[i + 1].toString()
									.toLowerCase() + ","
							+ perception.floor.room[i].toString().toLowerCase()
							+ "," + pos + ").\n";
					adj += "\nadjacent(" + rpos + "," + pos + "," + (rpos + 1)
							+ "," + pos + ").";
					adj += "\nadjacent(" + (rpos + 1) + "," + pos + "," + rpos
							+ "," + pos + ").";
				}
				if (pos < perception.floor.width) {
					adj += "\nadjacent(" + rpos + "," + pos + "," + rpos + ","
							+ (pos + 1) + ").";
					adj += "\nadjacent(" + rpos + "," + (pos + 1) + "," + rpos
							+ "," + pos + ").";
				}
				
				

			}
		}
		System.out.println(doors + room);

		try {
			// Create file

			FileWriter fstream = new FileWriter("dlv/ciccio_pasticcio_back.dl");
			BufferedWriter out = new BufferedWriter(fstream);
			out.write("%ciccio_pasticcio_back.dl");
			out.write(obj + room + position + doors + adj);

			out.close();
		} catch (Exception e) {// Catch exception if any
			System.err.println("Error: " + e.getMessage());
		}

	}

	public void print_initial(int x, int y) {

		String res = "\n";

		int pos;

		res = res + "at(ciccio,"
				+ perception.floor.room[x].toString().toLowerCase() + ","
				+ (y + 1) + ").\n";

		for (int i = 0; i < perception.floor.length; i++) {
			System.out.println("ROOM  " + i + perception.floor.room[i].toString());
			for (int j = 0; j <= perception.floor.width; j++) {
				pos = j + 1;

				if (perception.floor.room[i] == Floor.roomType.BEDROOM
						&& perception.floor.get(i, j) == Square.Type.SMOKING) {
					res = res + "at("
							+ Square.Type.SMOKING.toString().toLowerCase()
							+ ","
							+ perception.floor.room[i].toString().toLowerCase()
							+ "," + pos + ").\n";
				}

				if (perception.floor.get(i, j) == Square.Type.FLOWERS) {
					res = res + "at("
							+ Square.Type.FLOWERS.toString().toLowerCase()
							+ ","
							+ perception.floor.room[i].toString().toLowerCase()
							+ "," + pos + ").\n";
				}

				if (perception.floor.get(i, j) == Square.Type.TABLE) {
					res = res + "at("
							+ Square.Type.TABLE.toString().toLowerCase() + ","
							+ perception.floor.room[i].toString().toLowerCase()
							+ "," + pos + ").\n";
				}

				if (perception.floor.get(i, j) == Square.Type.MEAL)
					res = res + "at("
							+ Square.Type.MEAL.toString().toLowerCase() + ","
							+ perception.floor.room[i].toString().toLowerCase()
							+ "," + pos + ").\n";

			
			
				if (perception.floor.room[i] == Floor.roomType.ENTRANCE) {
					if (perception.floor.get(i-1, j) == Square.Type.DOOR)
				
					res = res + "at("
							+ Square.Type.ENTRANCE.toString().toLowerCase()
							+ ","
							+ perception.floor.room[i].toString().toLowerCase()
							+ "," + pos + ").\n";
					
					System.out.println("room entrance");
				}
				}
				
	
		}
		System.out.println(res);

		try {
			// Create file

			FileWriter fstream = new FileWriter(
					"dlv/ciccio_pasticcio_initial.plan");
			BufferedWriter out = new BufferedWriter(fstream);
			out.write("%ciccio_pasticcio_initial.plan");
			out.write("\ninitially:" + res);

			out.close();
		} catch (Exception e) {// Catch exception if any
			System.err.println("Error: " + e.getMessage());
		}
	}

	public void executePlan() {
		int countMoves = 0;
		Coord currentPos;

		meal_ready_actions = dlvwrapper.getPlan("prepare_meal");
		countMoves += meal_ready_actions.size();

		if (countMoves < stepValue) {
			currentPos = meal_ready_actions.get(meal_ready_actions.size() - 1);
			print_initial((currentPos.x), (currentPos.y));
			suit_up_actions = dlvwrapper.getPlan("dress_up");
			countMoves += suit_up_actions.size();
		}

		if (countMoves < stepValue) {

			currentPos = suit_up_actions.get(suit_up_actions.size() - 1);
			print_initial((currentPos.x), (currentPos.y));
			take_meal_actions = dlvwrapper.getPlan("take_meal");
			countMoves += suit_up_actions.size();
		}

		if (countMoves < stepValue) {
			currentPos = take_meal_actions.get(take_meal_actions.size() - 1);
			print_initial((currentPos.x), (currentPos.y));
			table_ready_actions = dlvwrapper.getPlan("table_ready");
			countMoves += table_ready_actions.size();
		}

		if (countMoves < stepValue) {
			currentPos = table_ready_actions
					.get(table_ready_actions.size() - 1);
			print_initial((currentPos.x), (currentPos.y));
			flowers_taken_actions = dlvwrapper.getPlan("take_flowers");
			countMoves += flowers_taken_actions.size();
		}

		if (countMoves < stepValue) {
			currentPos = flowers_taken_actions
					.get(flowers_taken_actions.size() - 1);
			print_initial((currentPos.x), (currentPos.y));
			entrance_actions = dlvwrapper.getPlan("wait_renata");
			countMoves += entrance_actions.size();
		}
		if (countMoves>stepValue){
			System.err.println("Error: Il pathlength � pi� lungo dello stepvalue ");
		
		}

	}

	public void executeAction() {
		
		// l'energia viene decrementata nel mainloop
		if (energy > 0) {
			if (meal_ready_actions.size() == 0) {
				currAction = Action.Type.PREPARE_MEAL;

			} else {

				nextPos = meal_ready_actions.get(0).y;
				nextRoom = meal_ready_actions.get(0).x;
				meal_ready_actions.remove(0);
				moveCiccio(nextPos, nextRoom);

			}

			if (MEAL_READY) {

				if (suit_up_actions.size() == 0) {
					currAction = Action.Type.DRESS_UP;
				} else {
					nextPos = suit_up_actions.get(0).y;
					nextRoom = suit_up_actions.get(0).x;
					suit_up_actions.remove(0);
					moveCiccio(nextPos, nextRoom);
				}
			}

			if (SUIT_UP) {
				if (take_meal_actions.size() == 0) {
					currAction = Action.Type.TAKE_MEAL;
				} else {
					nextPos = take_meal_actions.get(0).y;
					nextRoom = take_meal_actions.get(0).x;
					take_meal_actions.remove(0);
					moveCiccio(nextPos, nextRoom);
				}
			}

			if (TAKE_MEAL) {
				if (table_ready_actions.size() == 0) {
					currAction = Action.Type.TABLE_READY;
				} else {
					nextPos = table_ready_actions.get(0).y;
					nextRoom = table_ready_actions.get(0).x;
					table_ready_actions.remove(0);
					moveCiccio(nextPos, nextRoom);
				}
			}

			if (TABLE_READY) {
				if (flowers_taken_actions.size() == 0) {
					currAction = Action.Type.TAKE_FLOWERS;
				} else {
					nextPos = flowers_taken_actions.get(0).y;
					nextRoom = flowers_taken_actions.get(0).x;
					flowers_taken_actions.remove(0);
					moveCiccio(nextPos, nextRoom);
				}
			}

			if (FLOWERS_TAKEN) {
				if (entrance_actions.size() == 0) {
					currAction = Action.Type.WAIT_RENATA;
				} else {
					nextPos = entrance_actions.get(0).y;
					nextRoom = entrance_actions.get(0).x;
					entrance_actions.remove(0);
					moveCiccio(nextPos, nextRoom);
				}
			}

		

			if (ENTRANCE)
				goalReached = true;

		}else{
			died = true;
		}
		
		
		/*
		 * for (int i = 0; i < meal_ready_actions.size(); i++) {
		 * System.out.println("*********************************");
		 * System.out.println("moves : \n" + i +
		 * meal_ready_actions.get(i).toString());
		 * 
		 * }
		 */
	}

	@Override
	public void setCurrentPosition(int room, int pos) {
		this.x = room;
		this.y = pos;
	}

	public void moveCiccio(int nextPos, int nextRoom) {
		System.out.println("currpos -> x= " + x + " y= " + y);
		System.out.println(" nextRoom -> " + nextRoom + " nextPos ->  "
				+ nextPos);
		if (this.x == nextRoom) {

			if (nextPos == (y + 1) && nextPos <= perception.floor.width) {
				System.out.println("executeAction == EAST ");
				currAction = Action.Type.EAST;
			}

			if (nextPos == (y - 1) && nextPos >= 0) {
				System.out.println("executeAction == WEST ");
				currAction = Action.Type.WEST;
			}
		}

		if (this.y == nextPos) {
			if (nextRoom == (x - 1) && nextRoom >= 0) {
				System.out.println("executeAction == NORTH ");
				currAction = Action.Type.NORTH;
			}

			if (nextRoom == (x + 1) && nextRoom <= perception.floor.length) {
				System.out.println("executeAction == SOUTH ");
				currAction = Action.Type.SOUTH;
			}
		}

	}
	

}
